home *** CD-ROM | disk | FTP | other *** search
- /*
- * Copyright 1994, 1996, Silicon Graphics, Inc.
- * All Rights Reserved.
- *
- * This is UNPUBLISHED PROPRIETARY SOURCE CODE of Silicon Graphics, Inc.;
- * the contents of this file may not be disclosed to third parties, copied or
- * duplicated in any form, in whole or in part, without the prior written
- * permission of Silicon Graphics, Inc.
- *
- * RESTRICTED RIGHTS LEGEND:
- * Use, duplication or disclosure by the Government is subject to restrictions
- * as set forth in subdivision (c)(1)(ii) of the Rights in Technical Data
- * and Computer Software clause at DFARS 252.227-7013, and/or in similar or
- * successor clauses in the FAR, DOD or NASA FAR Supplement. Unpublished -
- * rights reserved under the Copyright Laws of the United States.
- */
-
- /*
- * shadow.c - OpenGL example drawing a shadowed cube
- *
- * Escape Key - exit the program
- *
- * r Key - toggle cube rotation
- * f Key - toggle filled/outlined
- * s Key - toggle parallel/perspective shadow/light
- * l Key - toggle lighting
- *
- * Left/Right Arrow Key - move light
- * Up/Down Arrow Key - move light
- *
- * Left Mousebutton, down - start moving the eye
- * Left Mousebutton, up - stop moving the eye
- * Mouse pointer location - position eye
- */
-
- #include <Xm/Xm.h>
- #include <Xm/AtomMgr.h> /* for WMProtocol */
- #include <Xm/Protocols.h>
-
- #include <X11/keysym.h>
-
- #include <GL/GLwMDrawA.h> /* for Mixed Model OpenGL */
- #include <GL/gl.h>
- #include <GL/glu.h>
- #include <GL/glx.h>
-
- /* Function Prototypes */
-
- void initCB (Widget w, XtPointer client_data, GLwDrawingAreaCallbackStruct *call_data);
- void exposeCB(Widget w, XtPointer dummy0, XtPointer dummy1);
- void resizeCB(Widget w, XtPointer dummy0, GLwDrawingAreaCallbackStruct *call_data);
- void inputCB (Widget w, Display *display, GLwDrawingAreaCallbackStruct *call_data);
-
- GLvoid drawScene( GLvoid );
-
- /* Global Variables */
-
- static XtAppContext app_context;
- static GLXContext glx_context;
- static Display *display;
- static Window window;
- static XtWorkProcId wpid;
-
- static GLboolean b1_pressed = GL_FALSE;
-
- GLint xStart, yStart;
- GLfloat rotationX, rotationY;
-
- static int useLighting = 1;
- static int doFilled = 1;
- static int doRotation = 1;
- static int shadowType = 1;
-
- #define GREY 0
- #define RED 1
- #define GREEN 2
- #define BLUE 3
- #define CYAN 4
- #define MAGENTA 5
- #define YELLOW 6
- #define BLACK 7
-
- static float materialColor[8][4] = {
- { 0.8, 0.8, 0.8, 1.0 },
- { 0.8, 0.0, 0.0, 1.0 },
- { 0.0, 0.8, 0.0, 1.0 },
- { 0.0, 0.0, 0.8, 1.0 },
- { 0.0, 0.8, 0.8, 1.0 },
- { 0.8, 0.0, 0.8, 1.0 },
- { 0.8, 0.8, 0.0, 1.0 },
- { 0.0, 0.0, 0.0, 0.4 },
- };
-
- static float shadowPos[4] = { 0.0, 1.2, 0.0, 1.0 };
- static float lightAmb[4] = { 0.2, 0.2, 0.2, 1.0 };
- static float lightDiff[4] = { 0.8, 0.8, 0.8, 1.0 };
- static float lightSpec[4] = { 0.4, 0.4, 0.4, 1.0 };
-
- static float groundPlane[4] = { 0.0, 1.0, 0.0, 0.0 };
-
- static unsigned char shadowPattern[128] = {
- 0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xdd,
- 0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xdd,
- 0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xdd,
- 0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xdd,
- 0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xdd,
- 0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xdd,
- 0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xdd,
- 0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xdd,
- 0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xdd,
- 0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xdd,
- 0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xdd,
- 0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xdd,
- 0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xdd,
- 0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xdd,
- 0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xdd,
- 0x77, 0x77, 0x77, 0x77, 0xdd, 0xdd, 0xdd, 0xd
- };
-
- static float cube_vertexes[6][4][3] = {
- { { -0.3, 0.3, -0.3 },
- { -0.3, 0.0, -0.3 },
- { -0.3, 0.0, 0.3 },
- { -0.3, 0.3, 0.3 } },
-
- { { 0.3, 0.3, -0.3 },
- { 0.3, 0.3, 0.3 },
- { 0.3, 0.0, 0.3 },
- { 0.3, 0.0, -0.3 } },
-
- { { 0.3, 0.0, -0.3 },
- { -0.3, 0.0, -0.3 },
- { -0.3, 0.3, -0.3 },
- { 0.3, 0.3, -0.3 } },
-
- { { 0.3, 0.0, 0.3 },
- { 0.3, 0.3, 0.3 },
- { -0.3, 0.3, 0.3 },
- { -0.3, 0.0, 0.3 } },
-
- { { -0.3, 0.0, 0.3 },
- { -0.3, 0.0, -0.3 },
- { 0.3, 0.0, -0.3 },
- { 0.3, 0.0, 0.3 } },
-
- { { 0.3, 0.3, -0.3 },
- { -0.3, 0.3, -0.3 },
- { -0.3, 0.3, 0.3 },
- { 0.3, 0.3, 0.3 } }
- };
-
- static float cube_normals[6][3] = {
- { -1.0, 0.0, 0.0 },
- { 1.0, 0.0, 0.0 },
- { 0.0, 0.0, -1.0 },
- { 0.0, 0.0, 1.0 },
- { 0.0, -1.0, 0.0 },
- { 0.0, 1.0, 0.0 }
- };
-
- void
- main(int argc, char *argv[])
- {
- Atom WM_DELETE_WINDOW;
- Widget glw, toplevel;
-
- static String fallback_resources[] =
- {
- "*title: shadow: controlled by 'r' 's' 'f' 'l' and arrow keys",
- "*geometry: +100+100",
- "*glwidget*width: 600",
- "*glwidget*height: 384",
- "*glwidget*rgba: TRUE",
- "*glwidget*doublebuffer: TRUE",
-
- "*sgiMode: true", /* try to enable IRIX 5.2+ look & feel */
- "*useSchemes: all", /* and SGI schemes */
-
- NULL
- };
-
- toplevel = XtVaAppInitialize(
- &app_context, /* Application context */
- "OGLTemplates", /* Application class */
- NULL, 0, /* command line option list */
- &argc, argv, /* command line args */
- fallback_resources,
- NULL); /* end of argument list */
-
- glw = XtCreateManagedWidget("glwidget", glwMDrawingAreaWidgetClass, toplevel, NULL, 0);
-
- XtAddCallback(glw, GLwNginitCallback, (XtCallbackProc)initCB, NULL);
- XtAddCallback(glw, GLwNexposeCallback, (XtCallbackProc)exposeCB, NULL);
- XtAddCallback(glw, GLwNresizeCallback, (XtCallbackProc)resizeCB, NULL);
- XtAddCallback(glw, GLwNinputCallback, (XtCallbackProc)inputCB, (XtPointer)XtDisplay(toplevel));
-
- WM_DELETE_WINDOW = XmInternAtom(XtDisplay(toplevel), "WM_DELETE_WINDOW", False);
- XmAddWMProtocolCallback(toplevel, WM_DELETE_WINDOW, (XtCallbackProc)inputCB, (XtPointer)XtDisplay(toplevel));
-
-
- XtRealizeWidget(toplevel); /* instantiate it now */
- XtAppMainLoop(app_context); /* loop for events */
- }
-
- /*
- * initCB
- *
- * The initCB subroutine initializes graphics modes and
- * transformation matrices.
- */
-
- void
- initCB(Widget w, XtPointer d0, GLwDrawingAreaCallbackStruct *call_data)
- {
- GLfloat aspect;
- Arg args[1];
- XVisualInfo *vi;
-
- window = XtWindow(w);
- display = XtDisplay(w);
-
- XtSetArg(args[0], GLwNvisualInfo, &vi);
- XtGetValues(w, args, 1);
-
- glx_context = glXCreateContext(XtDisplay(w), vi, 0, GL_TRUE);
- GLwDrawingAreaMakeCurrent(w, glx_context);
-
- glClearColor( 0.0, 0.0, 0.0, 1.0 );
-
- glMatrixMode( GL_PROJECTION );
- aspect = (GLfloat) call_data->width / call_data->height;
- gluPerspective( 50.0, aspect, 1.0, 70.0 );
- glMatrixMode( GL_MODELVIEW );
-
- glTranslatef(0.0, 0.0, -4.0);
- glRotatef(45.0, 1.0, 0.0, 0.0);
-
- glEnable(GL_LIGHTING);
- glEnable(GL_LIGHT0);
- glLightfv(GL_LIGHT0, GL_POSITION, shadowPos);
- glLightfv(GL_LIGHT0, GL_AMBIENT, lightAmb);
- glLightfv(GL_LIGHT0, GL_DIFFUSE, lightDiff);
- glLightfv(GL_LIGHT0, GL_SPECULAR, lightSpec);
-
- glPolygonStipple((const GLubyte *)shadowPattern);
- glPointSize(4.0);
-
- wpid = XtAppAddWorkProc(app_context, (XtWorkProc)drawScene, NULL);
- }
-
-
- /* exposeCB() and resizeCB() are called when the window
- * is uncovered, moved, or resized.
- */
-
- void
- exposeCB(Widget w, XtPointer d0, XtPointer d1)
- {
- GLwDrawingAreaMakeCurrent(w, glx_context);
- drawScene();
- }
-
- void
- resizeCB(Widget w, XtPointer d0, GLwDrawingAreaCallbackStruct *call_data)
- {
- GLfloat aspect;
-
- glViewport(0, 0, (GLuint) call_data->width, (GLuint) call_data->height);
-
- aspect = (GLfloat) call_data->width / call_data->height;
-
- glMatrixMode( GL_PROJECTION );
- glLoadIdentity();
- gluPerspective( 50.0, aspect, 1.0, 70.0 );
- glMatrixMode( GL_MODELVIEW );
- }
-
- void
- inputCB(Widget w, Display *display, GLwDrawingAreaCallbackStruct *call_data)
- {
- char buf[2];
- KeySym keysym;
- int rc;
-
- GLboolean do_exit = GL_FALSE;
-
- switch(call_data->reason)
- {
- case 6666: do_exit = GL_TRUE; break;
- case GLwCR_INPUT:
- switch(call_data->event->type)
- {
- case KeyPress:
- XLookupString((XKeyEvent *) call_data->event, buf, 2, &keysym, NULL);
- switch (keysym)
- {
- case XK_Escape:
- do_exit = GL_TRUE;
- break;
- case XK_L: case XK_l:
- useLighting = !useLighting;
- useLighting ? glEnable(GL_LIGHTING) : glDisable(GL_LIGHTING);
- break;
- case XK_F: case XK_f:
- doFilled = !doFilled;
- break;
- case XK_R: case XK_r:
- doRotation = !doRotation;
- if (doRotation)
- wpid = XtAppAddWorkProc(app_context, (XtWorkProc)drawScene, NULL);
- else
- {
- XtRemoveWorkProc(wpid);
- wpid = NULL;
- }
- break;
- case XK_S: case XK_s:
- shadowType = !shadowType;
- if (shadowType) shadowPos[3] = 1.0;
- else shadowPos[3] = 0.0;
- break;
- case XK_Left:
- shadowPos[0]-=.1;
- break;
- case XK_Right:
- shadowPos[0]+=.1;
- break;
- case XK_Up:
- shadowPos[1]+=.1;
- break;
- case XK_Down:
- shadowPos[1]-=.1;
- break;
- }
- break;
-
- case ButtonPress:
- if (((XButtonEvent *)call_data->event)->button == 1)
- {
- b1_pressed = GL_TRUE;
- xStart = ((XButtonEvent *)call_data->event)->x_root;
- yStart = ((XButtonEvent *)call_data->event)->y_root;
- }
- break;
-
- case ButtonRelease:
- if (((XButtonEvent *)call_data->event)->button == 1)
- b1_pressed = GL_FALSE;
- break;
-
- case MotionNotify:
- {
- GLint xPos, yPos;
- GLint xOffset, yOffset;
-
- if (! b1_pressed) break;
-
- xPos = ((XMotionEvent *)call_data->event)->x_root;
- yPos = ((XMotionEvent *)call_data->event)->y_root;
-
- /* Using the stored and current mouse positions, compute how far
- * the mouse moved */
- xOffset = xPos - xStart;
- yOffset = yPos - yStart;
-
- /* Adjust the eye position based on the mouse position */
- rotationY += xOffset;
- rotationX += yOffset;
-
- /* Update the stored mouse position for later use */
- xStart = xPos;
- yStart = yPos;
- }
- break;
- }
- break;
-
- default:
- printf("inputCB: reason: %d event->type: %d\n", call_data->reason, call_data->event->type);
- break;
- }
-
- if (do_exit)
- {
- XtCloseDisplay(display);
- exit(0);
- }
-
- if (!doRotation && (XPending(display) == 0)) drawScene();
- }
-
- static void
- drawCube()
- {
- int i;
-
- glBegin(GL_QUADS);
- for (i = 0; i < 6; ++i)
- {
- glNormal3fv(&cube_normals[i][0]);
- glVertex3fv(&cube_vertexes[i][0][0]);
- glVertex3fv(&cube_vertexes[i][1][0]);
- glVertex3fv(&cube_vertexes[i][2][0]);
- glVertex3fv(&cube_vertexes[i][3][0]);
- }
- glEnd();
- }
-
- static void
- myShadowMatrix(float ground[4], float light[4])
- {
- int i, j;
- float dot;
- float shadowMat[4][4];
-
- dot = ground[0] * light[0] +
- ground[1] * light[1] +
- ground[2] * light[2] +
- ground[3] * light[3];
-
- // fp exceptions may occur whenever the light comes
- // (nearly) directly in an 90 degree angle (compared to the)
- // ground normal. In reality there's no shadow when the sun
- // (or any light) goes down...
-
- // lighting should be turned off, as the shadow itself is not
- // lighted at all (this will avoid fp exceptions)
-
- shadowMat[0][0] = dot - light[0] * ground[0];
- shadowMat[1][0] = 0.0 - light[0] * ground[1];
- shadowMat[2][0] = 0.0 - light[0] * ground[2];
- shadowMat[3][0] = 0.0 - light[0] * ground[3];
-
- shadowMat[0][1] = 0.0 - light[1] * ground[0];
- shadowMat[1][1] = dot - light[1] * ground[1];
- shadowMat[2][1] = 0.0 - light[1] * ground[2];
- shadowMat[3][1] = 0.0 - light[1] * ground[3];
-
- shadowMat[0][2] = 0.0 - light[2] * ground[0];
- shadowMat[1][2] = 0.0 - light[2] * ground[1];
- shadowMat[2][2] = dot - light[2] * ground[2];
- shadowMat[3][2] = 0.0 - light[2] * ground[3];
-
- shadowMat[0][3] = 0.0 - light[3] * ground[0];
- shadowMat[1][3] = 0.0 - light[3] * ground[1];
- shadowMat[2][3] = 0.0 - light[3] * ground[2];
- shadowMat[3][3] = dot - light[3] * ground[3];
-
- glMultMatrixf((const GLfloat*)shadowMat);
-
- /* for (i=0; i<4; i++)
- printf("%5.3f %5.3f %5.3f %5.3f\n", shadowMat[i][0], shadowMat[i][1], shadowMat[i][2], shadowMat[i][3]);
- printf("\n\n");
- */
- }
-
- GLvoid
- drawScene( GLvoid )
- {
- static GLfloat rotCube;
- static GLfloat cubeXform[4][4];
-
- glClear( GL_COLOR_BUFFER_BIT );
-
- glDisable(GL_CULL_FACE);
- glPolygonMode(GL_FRONT, GL_FILL);
- glPolygonMode(GL_BACK, GL_LINE);
-
- glPushMatrix();
- glRotatef(rotationX, 1.0, 0.0, 0.0);
- glRotatef(rotationY, 0.0, 1.0, 0.0);
-
- glLightfv(GL_LIGHT0, GL_POSITION, shadowPos);
-
- if (useLighting)
- {
- glNormal3fv(groundPlane);
- glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, &materialColor[BLUE][0]);
- }
- else glColor4fv(&materialColor[BLUE][0]);
-
- glBegin(GL_QUADS);
- glVertex3f( 2.0, 0.0,-2.0);
- glVertex3f(-2.0, 0.0,-2.0);
- glVertex3f(-2.0, 0.0, 2.0);
- glVertex3f( 2.0, 0.0, 2.0);
- glEnd();
-
- glDisable(GL_LIGHTING); // shadow itself is not lighted
-
- if (doRotation) // of cube
- {
- glPushMatrix();
- glLoadIdentity();
- rotCube += 5; if (rotCube >= 360.0) rotCube = 0.0;
- glRotatef(rotCube, 0, 1, 0);
- glGetFloatv(GL_MODELVIEW_MATRIX, (GLfloat *)cubeXform);
- glPopMatrix();
- }
-
- if (doFilled)
- {
- glEnable(GL_POLYGON_STIPPLE);
- glPolygonMode(GL_FRONT_AND_BACK, GL_FILL);
- }
- else glPolygonMode(GL_FRONT_AND_BACK, GL_LINE);
-
- glPushMatrix();
- myShadowMatrix(groundPlane, shadowPos);
- glMultMatrixf((const GLfloat *) cubeXform);
-
- glColor3f(0.0, 0.0, 0.0);
- drawCube(); // draw ground shadow
- glPopMatrix();
-
- if (shadowPos[3] != 0.0)
- {
- glColor3f(1.0, 1.0, 1.0); // draw pointlight
- glBegin(GL_POINTS);
- glVertex3fv(shadowPos);
- glEnd();
- }
-
- glEnable(GL_CULL_FACE);
- glDisable(GL_POLYGON_STIPPLE);
- if (useLighting) glEnable(GL_LIGHTING);
-
- glPushMatrix();
- glMultMatrixf((const GLfloat *) cubeXform);
-
- if (useLighting) glMaterialfv(GL_FRONT_AND_BACK, GL_AMBIENT_AND_DIFFUSE, &materialColor[RED][0]);
- else glColor4fv(&materialColor[RED][0]);
-
- drawCube(); // draw cube
- glPopMatrix();
-
- glPopMatrix();
-
- glXSwapBuffers(display, window); // or GLwDrawingAreaSwapBuffers(glwidget)
- }
-